/**
 * 
 */
package org.drl.tvkit;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.drl.tvkit.base.BaseActivityManager;
import org.drl.tvkit.base.BaseManagerInterface;
import org.drl.tvkit.base.fragment.TVFragment;
import org.drl.tvkit.dao.DataBaseManager;
import org.drl.tvkit.dao.FileRecordTable;
import org.drl.tvkit.error.GlobalCrashHandler;
import org.drl.tvkit.task.LevelThreadFactory;
import org.drl.tvkit.task.TaskSub;
import org.drl.tvkit.task.TwoTask;
import org.drl.tvkit.util.L;

import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.WindowManager;

import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;

/**
 * @author Darry Ring
 * 
 */
public class KitApplication extends Application {

	private static KitApplication mInstance = null;

	public static final KitApplication getInstance() {
		return mInstance;
	}

	private ImageLoader mImageLoader;
	private ExecutorService mExecutorService;
	private Handler HANDLER;
	private Map<String, Class<? extends TVFragment>> regterTvFragments = new HashMap<String, Class<? extends TVFragment>>();
	private TwoTask mVooleTask;
	private List<Object> registeredManagers;
	private int scrrenWidht;
	private int screenHeight;
	float density = 0;

	@Override
	public void onCreate() {
		mInstance = this;
		System.setProperty("sun.net.client.defaultConnectTimeout", "30000");
		System.setProperty("sun.net.client.defaultReadTimeout", "30000");
		mVooleTask = new TwoTask();
		onPreloading();
		super.onCreate();
		initErrorTry();
		HANDLER = new Handler();
		initExecutorService();
		DataBaseManager.newBuilder();
		initObject();
		initImageLoader(getApplicationContext());
		initDisplayInfo();
		initRegeterFragment();
		runTaskSub(FileRecordTable.getInstance());
	}

	private void initErrorTry() {
		GlobalCrashHandler crashHandler = new GlobalCrashHandler();
		Thread.setDefaultUncaughtExceptionHandler(crashHandler);
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
		L.i(Config.APP_LOG_TAG, "onLowMemory-->");
	}

	@SuppressLint("NewApi")
	@Override
	public void onTrimMemory(int level) {
		super.onTrimMemory(level);
		L.i(Config.APP_LOG_TAG, "onTrimMemory-->" + level);
	}

	@SuppressWarnings("deprecation")
	private void initDisplayInfo() {
		WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
		int windowHeight = wm.getDefaultDisplay().getHeight();
		int windowWidth = wm.getDefaultDisplay().getWidth();
		screenHeight = windowHeight;
		scrrenWidht = windowWidth;
		DisplayMetrics displayMetrics = new DisplayMetrics();
		displayMetrics = getResources().getDisplayMetrics();
		density = displayMetrics.density;
	}

	private void onPreloading() {
		mVooleTask.start();
	}

	private void initObject() {
		registeredManagers = new ArrayList<Object>();
	}

	private void initRegeterFragment() {
		// ---------------------------------------------------------------------------------------------
	}

	private void initExecutorService() {
		mExecutorService = Executors.newFixedThreadPool(4,
				new LevelThreadFactory());
	}

	private void initImageLoader(Context context) {
		// This configuration tuning is custom. You can tune every option, you
		// may tune some of them,
		// or you can create default configuration by
		// ImageLoaderConfiguration.createDefault(this);
		// method.
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				context)
				.threadPriority(Thread.NORM_PRIORITY - 2)
				.denyCacheImageMultipleSizesInMemory()
				.diskCacheFileNameGenerator(new Md5FileNameGenerator())
				.diskCacheSize(50 * 1024 * 1024)
				// 50 Mb
				.tasksProcessingOrder(QueueProcessingType.LIFO)
				.threadPriority(Thread.NORM_PRIORITY - 2)
				// default
				.tasksProcessingOrder(QueueProcessingType.FIFO)
				// default
				.denyCacheImageMultipleSizesInMemory()
				.memoryCache(new LruMemoryCache(6 * 1024 * 1024))
				.memoryCacheSize(6 * 1024 * 1024).memoryCacheSizePercentage(13) // default
				.writeDebugLogs() // Remove for release app
				.build();
		// Initialize ImageLoader with configuration.
		mImageLoader = ImageLoader.getInstance();
		mImageLoader.init(config);
	}

	public ImageLoader getImageLoader() {
		return mImageLoader;
	}

	public void addManager(Object obj) {
		registeredManagers.add(obj);
	}

	public void removeManager(Object obj) {
		registeredManagers.remove(obj);
	}

	@SuppressWarnings("unchecked")
	public <T extends BaseManagerInterface> Collection<T> getManagers(
			Class<T> cls) {
		Collection<T> collection = null;
		if (collection == null) {
			collection = new ArrayList<T>();
			for (Object manager : registeredManagers)
				if (cls.isInstance(manager))
					collection.add((T) manager);
			collection = Collections.unmodifiableCollection(collection);
		}
		return collection;
	}

	/**
	 * 在第二个线程里面执行模块异步处理
	 * 
	 * @param _taskSub
	 */
	public final void runTaskSub(TaskSub _taskSub) {
		if (mVooleTask != null) {
			mVooleTask.addTaskSub(_taskSub);
		}
	}

	public void runBackground(Runnable run) {
		if (mExecutorService != null) {
			mExecutorService.execute(run);
		} else {
			new Thread(run).start();
		}
	}

	public void runOnUiThread(Runnable run) {
		HANDLER.post(run);
	}

	public void runOnUiThread(Runnable run, long delayMillis) {
		HANDLER.postDelayed(run, delayMillis);
	}

	protected void regterTVFragment(String key,
			Class<? extends TVFragment> _class) {
		regterTvFragments.put(key, _class);
	}

	public final Class<? extends TVFragment> getTVFragment(String key) {
		return regterTvFragments.get(key);
	}

	public final Map<String, Class<? extends TVFragment>> getRegterTvFragments() {
		return java.util.Collections.unmodifiableMap(regterTvFragments);
	}

	/**
	 * 软件重启
	 */
	public final void restart() {
		if (mExecutorService != null) {
			mExecutorService.shutdown();
			mExecutorService = null;
		}
		HANDLER.post(new Runnable() {
			@Override
			public void run() {
				BaseActivityManager.getInstance().onfinishAllActivity();
				android.os.Process.killProcess(android.os.Process.myPid());
			}
		});
	}

	public final void restart(long time) {
		if (mExecutorService != null) {
			mExecutorService.shutdown();
			mExecutorService = null;
		}
		HANDLER.postDelayed(new Runnable() {
			@Override
			public void run() {
				BaseActivityManager.getInstance().onfinishAllActivity();
				android.os.Process.killProcess(android.os.Process.myPid());
			}
		}, time);
	}

	public final int getScreenWidth() {
		return scrrenWidht;
	}

	public final int getScreenHeight() {
		return screenHeight;
	}

}
